/*
 * Selling Partner API for Tokens
 * The Selling Partner API for Tokens provides a secure way to access a customer's PII (Personally Identifiable Information). You can call the Tokens API to get a Restricted Data Token (RDT) for one or more restricted resources that you specify. The RDT authorizes subsequent calls to restricted operations that correspond to the restricted resources that you specified.  For more information, see the [Tokens API Use Case Guide](doc:tokens-api-use-case-guide).
 *
 * OpenAPI spec version: 2021-03-01
 *
 *
 * NOTE: This class is auto generated by the swagger code generator program.
 * https://github.com/swagger-api/swagger-codegen.git
 * Do not edit the class manually.
 */

package software.amazon.spapi.api.tokens.v2021_03_01;

import com.amazon.SellingPartnerAPIAA.LWAAccessTokenCache;
import com.amazon.SellingPartnerAPIAA.LWAAccessTokenCacheImpl;
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationCredentials;
import com.amazon.SellingPartnerAPIAA.LWAAuthorizationSigner;
import com.amazon.SellingPartnerAPIAA.LWAException;
import com.amazon.SellingPartnerAPIAA.RestrictedDataTokenSigner;
import com.google.gson.reflect.TypeToken;
import io.github.bucket4j.Bucket;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import software.amazon.spapi.ApiCallback;
import software.amazon.spapi.ApiClient;
import software.amazon.spapi.ApiException;
import software.amazon.spapi.ApiResponse;
import software.amazon.spapi.Configuration;
import software.amazon.spapi.Pair;
import software.amazon.spapi.ProgressRequestBody;
import software.amazon.spapi.StringUtil;
import software.amazon.spapi.models.tokens.v2021_03_01.CreateRestrictedDataTokenRequest;
import software.amazon.spapi.models.tokens.v2021_03_01.CreateRestrictedDataTokenResponse;

public class TokensApi {
    private ApiClient apiClient;
    private Boolean disableRateLimiting;

    public TokensApi(ApiClient apiClient, Boolean disableRateLimiting) {
        this.apiClient = apiClient;
        this.disableRateLimiting = disableRateLimiting;
    }

    private final Configuration config = Configuration.get();

    public final Bucket createRestrictedDataTokenBucket = Bucket.builder()
            .addLimit(config.getLimit("TokensApi-createRestrictedDataToken"))
            .build();

    /**
     * Build call for createRestrictedDataToken
     *
     * @param body The restricted data token request details. (required)
     * @param progressRequestListener Progress request listener
     * @return Call to execute
     * @throws ApiException If fail to serialize the request body object
     * @throws LWAException If calls to fetch LWA access token fails
     */
    private okhttp3.Call createRestrictedDataTokenCall(
            CreateRestrictedDataTokenRequest body,
            final ProgressRequestBody.ProgressRequestListener progressRequestListener)
            throws ApiException, LWAException {
        Object localVarPostBody = body;

        // create path and map variables
        String localVarPath = "/tokens/2021-03-01/restrictedDataToken";

        List<Pair> localVarQueryParams = new ArrayList<Pair>();
        List<Pair> localVarCollectionQueryParams = new ArrayList<Pair>();

        Map<String, String> localVarHeaderParams = new HashMap<String, String>();

        Map<String, Object> localVarFormParams = new HashMap<String, Object>();

        final String[] localVarAccepts = {"application/json"};
        final String localVarAccept = apiClient.selectHeaderAccept(localVarAccepts);
        if (localVarAccept != null) localVarHeaderParams.put("Accept", localVarAccept);

        final String[] localVarContentTypes = {"application/json"};
        final String localVarContentType = apiClient.selectHeaderContentType(localVarContentTypes);
        localVarHeaderParams.put("Content-Type", localVarContentType);

        return apiClient.buildCall(
                localVarPath,
                "POST",
                localVarQueryParams,
                localVarCollectionQueryParams,
                localVarPostBody,
                localVarHeaderParams,
                localVarFormParams,
                progressRequestListener);
    }

    private okhttp3.Call createRestrictedDataTokenValidateBeforeCall(
            CreateRestrictedDataTokenRequest body,
            final ProgressRequestBody.ProgressRequestListener progressRequestListener)
            throws ApiException, LWAException {
        // verify the required parameter 'body' is set
        if (body == null) {
            throw new ApiException(
                    "Missing the required parameter 'body' when calling createRestrictedDataToken(Async)");
        }

        return createRestrictedDataTokenCall(body, progressRequestListener);
    }

    /**
     * Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A restricted
     * resource is the HTTP method and path from a restricted operation that returns Personally Identifiable Information
     * (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use Case Guide for
     * a list of restricted operations. Use the RDT returned here as the access token in subsequent calls to the
     * corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ---- | | 1 |
     * 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were applied
     * to the requested operation, when available. The table above indicates the default rate and burst values for this
     * operation. Selling partners whose business demands require higher throughput may see higher rate and burst values
     * than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @param restrictedDataToken Restricted Data Token (optional)
     * @return CreateRestrictedDataTokenResponse
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public CreateRestrictedDataTokenResponse createRestrictedDataToken(
            CreateRestrictedDataTokenRequest body, String restrictedDataToken) throws ApiException, LWAException {
        ApiResponse<CreateRestrictedDataTokenResponse> resp =
                createRestrictedDataTokenWithHttpInfo(body, restrictedDataToken);
        return resp.getData();
    }

    /**
     * Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A restricted
     * resource is the HTTP method and path from a restricted operation that returns Personally Identifiable Information
     * (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use Case Guide for
     * a list of restricted operations. Use the RDT returned here as the access token in subsequent calls to the
     * corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ---- | | 1 |
     * 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were applied
     * to the requested operation, when available. The table above indicates the default rate and burst values for this
     * operation. Selling partners whose business demands require higher throughput may see higher rate and burst values
     * than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @return CreateRestrictedDataTokenResponse
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public CreateRestrictedDataTokenResponse createRestrictedDataToken(CreateRestrictedDataTokenRequest body)
            throws ApiException, LWAException {
        ApiResponse<CreateRestrictedDataTokenResponse> resp = createRestrictedDataTokenWithHttpInfo(body, null);
        return resp.getData();
    }

    /**
     * Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A restricted
     * resource is the HTTP method and path from a restricted operation that returns Personally Identifiable Information
     * (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use Case Guide for
     * a list of restricted operations. Use the RDT returned here as the access token in subsequent calls to the
     * corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ---- | | 1 |
     * 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were applied
     * to the requested operation, when available. The table above indicates the default rate and burst values for this
     * operation. Selling partners whose business demands require higher throughput may see higher rate and burst values
     * than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @param restrictedDataToken Restricted Data Token (optional)
     * @return ApiResponse&lt;CreateRestrictedDataTokenResponse&gt;
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public ApiResponse<CreateRestrictedDataTokenResponse> createRestrictedDataTokenWithHttpInfo(
            CreateRestrictedDataTokenRequest body, String restrictedDataToken) throws ApiException, LWAException {
        okhttp3.Call call = createRestrictedDataTokenValidateBeforeCall(body, null);

        if (restrictedDataToken != null) {
            okhttp3.Request request = call.request();
            request =
                    RestrictedDataTokenSigner.sign(request, restrictedDataToken, "TokensApi-createRestrictedDataToken");
            call = apiClient.getHttpClient().newCall(request);
        }

        if (disableRateLimiting || createRestrictedDataTokenBucket.tryConsume(1)) {
            Type localVarReturnType = new TypeToken<CreateRestrictedDataTokenResponse>() {}.getType();
            return apiClient.execute(call, localVarReturnType);
        } else throw new ApiException.RateLimitExceeded("createRestrictedDataToken operation exceeds rate limit");
    }

    /**
     * Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A restricted
     * resource is the HTTP method and path from a restricted operation that returns Personally Identifiable Information
     * (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use Case Guide for
     * a list of restricted operations. Use the RDT returned here as the access token in subsequent calls to the
     * corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ---- | | 1 |
     * 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were applied
     * to the requested operation, when available. The table above indicates the default rate and burst values for this
     * operation. Selling partners whose business demands require higher throughput may see higher rate and burst values
     * than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @return ApiResponse&lt;CreateRestrictedDataTokenResponse&gt;
     * @throws ApiException If fail to call the API, e.g. server error or cannot deserialize the response body
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public ApiResponse<CreateRestrictedDataTokenResponse> createRestrictedDataTokenWithHttpInfo(
            CreateRestrictedDataTokenRequest body) throws ApiException, LWAException {
        return createRestrictedDataTokenWithHttpInfo(body, null);
    }

    /**
     * (asynchronously) Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A
     * restricted resource is the HTTP method and path from a restricted operation that returns Personally Identifiable
     * Information (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use
     * Case Guide for a list of restricted operations. Use the RDT returned here as the access token in subsequent calls
     * to the corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ----
     * | | 1 | 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were
     * applied to the requested operation, when available. The table above indicates the default rate and burst values
     * for this operation. Selling partners whose business demands require higher throughput may see higher rate and
     * burst values than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @param callback The callback to be executed when the API call finishes
     * @return The request call
     * @throws ApiException If fail to process the API call, e.g. serializing the request body object
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public okhttp3.Call createRestrictedDataTokenAsync(
            CreateRestrictedDataTokenRequest body, final ApiCallback<CreateRestrictedDataTokenResponse> callback)
            throws ApiException, LWAException {
        return createRestrictedDataTokenAsync(body, callback, null);
    }
    /**
     * (asynchronously) Returns a Restricted Data Token (RDT) for one or more restricted resources that you specify. A
     * restricted resource is the HTTP method and path from a restricted operation that returns Personally Identifiable
     * Information (PII), plus a dataElements value that indicates the type of PII requested. See the Tokens API Use
     * Case Guide for a list of restricted operations. Use the RDT returned here as the access token in subsequent calls
     * to the corresponding restricted operations. **Usage Plan:** | Rate (requests per second) | Burst | | ---- | ----
     * | | 1 | 10 | The &#x60;x-amzn-RateLimit-Limit&#x60; response header returns the usage plan rate limits that were
     * applied to the requested operation, when available. The table above indicates the default rate and burst values
     * for this operation. Selling partners whose business demands require higher throughput may see higher rate and
     * burst values than those shown here. For more information, see [Usage Plans and Rate Limits in the Selling Partner
     * API](https://developer-docs.amazon.com/sp-api/docs/usage-plans-and-rate-limits-in-the-sp-api).
     *
     * @param body The restricted data token request details. (required)
     * @param callback The callback to be executed when the API call finishes
     * @param restrictedDataToken Restricted Data Token (optional)
     * @return The request call
     * @throws ApiException If fail to process the API call, e.g. serializing the request body object
     * @throws LWAException If calls to fetch LWA access token fails
     */
    public okhttp3.Call createRestrictedDataTokenAsync(
            CreateRestrictedDataTokenRequest body,
            final ApiCallback<CreateRestrictedDataTokenResponse> callback,
            String restrictedDataToken)
            throws ApiException, LWAException {

        ProgressRequestBody.ProgressRequestListener progressRequestListener = null;

        if (callback != null) {
            progressRequestListener = callback::onUploadProgress;
        }

        okhttp3.Call call = createRestrictedDataTokenValidateBeforeCall(body, progressRequestListener);

        if (restrictedDataToken != null) {
            okhttp3.Request request = call.request();
            request =
                    RestrictedDataTokenSigner.sign(request, restrictedDataToken, "TokensApi-createRestrictedDataToken");
            call = apiClient.getHttpClient().newCall(request);
        }

        if (disableRateLimiting || createRestrictedDataTokenBucket.tryConsume(1)) {
            Type localVarReturnType = new TypeToken<CreateRestrictedDataTokenResponse>() {}.getType();
            apiClient.executeAsync(call, localVarReturnType, callback);
            return call;
        } else throw new ApiException.RateLimitExceeded("createRestrictedDataToken operation exceeds rate limit");
    }

    public static class Builder {
        private LWAAuthorizationCredentials lwaAuthorizationCredentials;
        private String endpoint;
        private LWAAccessTokenCache lwaAccessTokenCache;
        private Boolean disableAccessTokenCache = false;
        private Boolean disableRateLimiting = false;

        public Builder lwaAuthorizationCredentials(LWAAuthorizationCredentials lwaAuthorizationCredentials) {
            this.lwaAuthorizationCredentials = lwaAuthorizationCredentials;
            return this;
        }

        public Builder endpoint(String endpoint) {
            this.endpoint = endpoint;
            return this;
        }

        public Builder lwaAccessTokenCache(LWAAccessTokenCache lwaAccessTokenCache) {
            this.lwaAccessTokenCache = lwaAccessTokenCache;
            return this;
        }

        public Builder disableAccessTokenCache() {
            this.disableAccessTokenCache = true;
            return this;
        }

        public Builder disableRateLimiting() {
            this.disableRateLimiting = true;
            return this;
        }

        public TokensApi build() {
            if (lwaAuthorizationCredentials == null) {
                throw new RuntimeException("LWAAuthorizationCredentials not set");
            }

            if (StringUtil.isEmpty(endpoint)) {
                throw new RuntimeException("Endpoint not set");
            }

            LWAAuthorizationSigner lwaAuthorizationSigner = null;
            if (disableAccessTokenCache) {
                lwaAuthorizationSigner = new LWAAuthorizationSigner(lwaAuthorizationCredentials);
            } else {
                if (lwaAccessTokenCache == null) {
                    lwaAccessTokenCache = new LWAAccessTokenCacheImpl();
                }
                lwaAuthorizationSigner = new LWAAuthorizationSigner(lwaAuthorizationCredentials, lwaAccessTokenCache);
            }

            return new TokensApi(
                    new ApiClient()
                            .setLWAAuthorizationSigner(lwaAuthorizationSigner)
                            .setBasePath(endpoint),
                    disableRateLimiting);
        }
    }
}
